import { AudioUrl, EnemyType, PlaneCamp, PlaneEvent } from "../Constant/Constant";
import BulletByEnemyFactory from "../Factory/BulletByEnemyFactory";
import EnemyFactory from "../Factory/EnemyFactory";
import AudioManager from "../Manager/AudioManager";
import BulletControl from "./BulletControl";

const { ccclass, property } = cc._decorator;

@ccclass
export default class EnemyControl extends cc.Component {

  @property(cc.SpriteFrame)
  defaultSpriteFrame = null

  @property(cc.SpriteFrame)
  dieSpritFrame = null

  // 敌机数据
  speed: number = 0
  hp: number = 1
  score: number = 0
  private isDied = false
  private _type: EnemyType = null

  // 子弹数据
  private _bulletSpeed: number = 300      // 子弹速度，参考值：300
  private _bulletInterval: number = 0.5   // 子弹间隔时间，参考值：0.5
  private _bulletRepeat: number = 0       // 子弹重复发射次数，0为不发射子弹
  private _bulletCount: number = 0        // 子弹已发射数量
  private _intervalId: number = null      // 子弹发射定时器ID

  get type(): EnemyType {
    return this._type
  }

  update(dt: number) {
    if (this.isDied != true) {
      this.move(dt)
    }
  }

  /**
   * 初始化
   * 根据敌机类型设置敌机属性
   * @param type 
   */
  public init(type: EnemyType) {
    this._type = type
    this.isDied = false
    // 初始化图片
    this.node.getComponent(cc.Sprite).spriteFrame = this.defaultSpriteFrame
    // 初始化敌机数据
    this._initEnemyData(type)
  }

  /**
   * 初始化不同类型敌机的数据
   * XXX: 可以从配置表中获取
   * @param type 
   */
  private _initEnemyData(type: EnemyType) {
    switch (type) {
      case EnemyType.TYPE_1:
        this.speed = 300
        this.hp = 1
        this.score = 1
        break;
      case EnemyType.TYPE_2:
        this.speed = 200
        this.hp = 2
        this.score = 2
        // 子弹
        this._bulletSpeed = 400
        this._bulletRepeat = 1
        this._bulletCount = 0
        // 开启子弹发射定时器
        this._startFireBulletTimeout()
        break;
      case EnemyType.TYPE_3:
        this.speed = 100
        this.hp = 3
        this.score = 5
        // 子弹
        this._bulletSpeed = 500
        this._bulletRepeat = 5
        this._bulletCount = 0
        // 开启子弹发射定时器
        this._startFireBulletTimeout()
        break;
      default:
        break;
    }
  }

  /**
   * 敌机向下移动
   * @param dt 
   */
  private move(dt: number): void {
    this.node.y -= this.speed * dt

    // 超出屏幕销毁，防止内存泄漏
    if (this.node.y < -this.node.height) {
      // PoolManager.instance.putNode(this.node)
      EnemyFactory.recycle(this.node)
    }
  }

  public die(): void {
    if (this.isDied) {
      return
    }
    this.isDied = true

    // 销毁音效
    // this.effectAudioSource.play()
    AudioManager.playEffect(AudioUrl.ENEMY_BLOWUP)
    // 发送击毁事件
    const event = new cc.Event.EventCustom(PlaneEvent.DIED, true)
    event.setUserData({ score: this.score })
    this.node.dispatchEvent(event);

    // 切换爆炸图片
    this.node.getComponent(cc.Sprite).spriteFrame = this.dieSpritFrame
    // 0.3s后销毁
    this.scheduleOnce(() => {
      EnemyFactory.recycle(this.node)
    }, 0.3)
  }

  /**
   * 创建子弹
   */
  private createBullet(): void {
    // 创建子弹
    const enemyNode = this.node
    const bulletNode = BulletByEnemyFactory.create(this.node, this._bulletSpeed)
    // 计算子弹发射位置，放置到敌机头部前面10像素的位置
    bulletNode.setPosition(enemyNode.x, enemyNode.y - (enemyNode.height * enemyNode.scaleY / 2) - 10)

    // 弹夹射空后，关闭定时器
    this._bulletCount++
    if (this._bulletCount >= this._bulletRepeat) {
      this._stopFireBulletTimeout()
    }
  }

  // 节点池回收节点
  unuse() {
    this._stopFireBulletTimeout()
  }

  // 开启发射子弹定时器
  private _startFireBulletTimeout() {
    console.log(`[EnemyControl] _startFireBulletTimeout()`)
    this._intervalId = setInterval(this.createBullet.bind(this), 1000 * this._bulletInterval)
  }

  // 关闭发射子弹定时器
  private _stopFireBulletTimeout() {
    console.log(`[EnemyControl] _stopFireBulletTimeout()`)
    clearInterval(this._intervalId)
    this._intervalId = null
  }

  /**
   * 当碰撞产生的时候调用
   * @param  {Collider} other 产生碰撞的另一个碰撞组件
   * @param  {Collider} self  产生碰撞的自身的碰撞组件
   */
  onCollisionEnter(other: cc.Collider, self: cc.Collider): void {
    if (other.tag !== 0) { return }

    // 被玩家子弹击中后销毁
    const bulletCtrl = other.getComponent(BulletControl)
    if (bulletCtrl == null) return

    if (bulletCtrl.from === PlaneCamp.PLAYER) {
      this.hp--
      if (this.hp <= 0) {
        this.die()
      }
    }
  }
}
